import celery
import json
import pagure
import rdflib

from .. import activitypub
from .. import model
from .. import settings

from . import broker
from . import broker_url
from . import database_session

log = celery.utils.log.get_task_logger(__name__)
log.setLevel(settings.LOG_LEVEL)

@broker.task
def handle_incoming_activity(person_id, activity):
    """
    A person has received a new Activity in its INBOX. This task is scheduled
    to look at that activity and update the Pagure database based on the
    Activity content.
    """
    
    with database_session() as (pagure_db, forgefed_graph):
        
        person = pagure_db.query(model.Person) \
                          .filter(model.Person.id == person_id) \
                          .one_or_none()
        
        # If the person doesn't exist, it means it was deleted after it received
        # an Activity but before the Activity was handled.
        if not person:
            log.info('Actor id(' + person_id + ') doesn\'t exist. Incoming '
                     'Activity will be ignored.')
            return
        
        if activity['type'] == 'Create':
            """
            The Person has received a Create Activity.
            """
            
            # Dereference the actor
            # actor = activitypub.fetch(activity['actor'])
            
            # Retrieve the object of the Activity
            object = forgefed_graph.get_json_node(activity['object'])
            
            if object['type'] == 'Note':
                log.debug('Somebody has Created a new Note.')
                
                model.test_or_set_remote_comment(pagure_db, forgefed_graph, activity['object'])
        
        if activity['type'] == 'Follow':
            """
            Somebody wants to follow this Person.
            """
            
            if activity['object'] != person.local_uri:
                log.info('Actor ' + person.local_uri + ' has received a Follow '
                         'request but the "object" doesn\'t match. '
                         'Activity will be ignored.')
                return
            
            if forgefed_graph.collection_contains(person.followers_uri,
                                                  activity['actor']):
                log.info('Actor ' + person.local_uri + ' is already following '
                         + activity['actor'] + '. Will ignore Follow request.')
                return
            
            # Add the remote object to our followers collection
            forgefed_graph.add_collection_item(person.followers_uri, activity['actor'])
            
            # Commit before accepting the Activity because we want the new
            # follower in the Followers collection before sending out the
            # Accept Activity.
            forgefed_graph.commit()
            
            # Automatically accept Follow requests.
            person.accept(activity['id'])
        
        if activity['type'] == 'Accept':
            """
            Somebody has sent us an Accept activity.
            """
            
            # What was accepted? Check if we have the "object" in our graph
            accepted_object = forgefed_graph.get_json_node(activity['object'])
            
            if not accepted_object:
                return
            
            if accepted_object['type'] == 'Offer':
                # Retrieve the "object" node of the Offer
                accepted_object['object'] = forgefed_graph.get_json_node(accepted_object['object'])
            
            # The remote actor has accepted our Ticket offer
            if accepted_object['type'] == 'Offer' \
            and accepted_object['actor'] == person.local_uri \
            and accepted_object['object']['type'] == 'Ticket' \
            and 'result' in activity \
            and activity['actor'] == accepted_object['to']:
                
                ticket = accepted_object['object']
                forgefed_graph.set((
                    rdflib.URIRef(ticket['id']),
                    rdflib.OWL.sameAs,
                    rdflib.URIRef(activity['result'])))
                
                log.debug('The ticket {} was accepted. A new ticket was created at {}'.format(ticket['id'], activity['result']))











